package cn.qg.search.service.token;



import cn.qg.beans.pojo.QgUser;
import cn.qg.common.MD5;
import cn.qg.common.RedisAPI;
import cn.qg.search.service.excetion.TokenAuthFailedException;
import com.alibaba.fastjson.JSON;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

/**
 * @author Charles
 * 2019/4/16 15:07
 */
@Service
public class TokenServiceImpl implements TokenService {

    @Resource
    private RedisAPI redisAPI;

    @Override
    public String replaceToken(String oldToken)throws Exception{

        // 1.验证token是否在置换保护期内
        // token:PC-userCode-userId-20194181344xx-6位随机
        // 获取旧token生成时间
        String[] tokenArr = oldToken.split("-");
        String tokenTime = tokenArr[3];
        Date tokenGenTime = null;
        try {
            tokenGenTime = new SimpleDateFormat("yyyyMMddHHmmss").parse(tokenTime);
        } catch (ParseException e) {
            throw  new TokenAuthFailedException("Token解析无效！");
        }

        // 计算token已存活时间
        long passedTime = new Date().getTime() - tokenGenTime.getTime();

        if(TOKEN_REPLACE_PROTECTION_TIME * 1000 > passedTime){
            throw  new TokenAuthFailedException("还未过Token置换保护期，还剩"+(TOKEN_REPLACE_PROTECTION_TIME - passedTime / 1000)+"s！");
        }

        // 2.判断是否还存活
        if(redisAPI.ttl(oldToken) <= 0){
            throw  new TokenAuthFailedException("Token已经失效！");
        }

        // 3.生成新token
        QgUser qgUse = this.getItripUserByToken(oldToken);
        String newJson = JSON.toJSONString(qgUse);
        String newToken = this.generateToken(qgUse);
        // 缓存新Token
        redisAPI.set(newToken,TOKEN_EXPIRE_TIME,newJson);

        // 4. 为了保护和置换请求并发的其他请求 需要将原有token重新缓存2分钟有效期
        redisAPI.set(oldToken,TOKEN_OLD_PROTECTION_TIME,newJson);

        return newToken;
    }

    /**
     * 根据token获取用户对象
     * @param token
     * @return
     * @throws Exception
     */
    public  QgUser getItripUserByToken(String token)throws Exception{
        if(redisAPI.exist(token)){
            String userJsonStr = redisAPI.get(token);
            // 转换为用户对象
            return JSON.parseObject(userJsonStr,  QgUser.class);
        }
        throw new TokenAuthFailedException("Token已经失效！获取用户对象失败！");
    }

    @Override
    public void deleteToken(String token) throws Exception {
        if(redisAPI.exist(token)){
            redisAPI.delete(token);
        }
    }

    @Override
    public boolean validateToken(String token) throws Exception {
        if(!redisAPI.exist(token)){
            return false;
        }
        return true;
    }

    @Override
    public void saveToken(String token,QgUser qgUse)throws Exception {
        // 未考虑不同客户端的存储
        redisAPI.set(token,TOKEN_EXPIRE_TIME, JSON.toJSONString(qgUse));
    }

    @Override
    public String generateToken(QgUser qgUse) {
        StringBuffer tokenStringBuffer = new StringBuffer(TOKEN_PREFIX);
        tokenStringBuffer.append("PC-");
        tokenStringBuffer.append(MD5.getMd5(qgUse.getRealName(),32)+"-");
        tokenStringBuffer.append(qgUse.getId()+"-");
        tokenStringBuffer.append(new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) +"-");
        // 2344Edsf-dfsr3-123343
        tokenStringBuffer.append(UUID.randomUUID().toString().replace("-","").substring(0,6));
        return tokenStringBuffer.toString();
    }
}
